home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 July / EnigmA AMIGA RUN 20 (1997)(G.R. Edizioni)(IT)[!][issue 1997-07 & 08][EAR-CD IV].iso / earcd / text / misc / nroff.lha / nroff / escape.c < prev    next >
C/C++ Source or Header  |  1997-03-28  |  21KB  |  1,120 lines

  1. /*
  2.  *    escape.c - Escape and special character input processing portion of
  3.  *               nroff word processor
  4.  *
  5.  *    adapted for atariST/TOS by Bill Rosenkranz 11/89
  6.  *    net:    rosenkra@hall.cray.com
  7.  *    CIS:    71460,17
  8.  *    GENIE:    W.ROSENKRANZ
  9.  *
  10.  *    original author:
  11.  *
  12.  *    Stephen L. Browning
  13.  *    5723 North Parker Avenue
  14.  *    Indianapolis, Indiana 46220
  15.  *
  16.  *    history:
  17.  *
  18.  *    - Originally written in BDS C;
  19.  *    - Adapted for standard C by W. N. Paul
  20.  *    - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
  21.  */
  22.  
  23. #undef NRO_MAIN                    /* extern globals */
  24.  
  25. #include <stdio.h>
  26. #include "nroff.h"
  27.  
  28.  
  29. /*------------------------------*/
  30. /*    expesc            */
  31. /*------------------------------*/
  32. expesc (p, q)
  33. char   *p;
  34. char   *q;
  35. {
  36.  
  37. /*
  38.  *    Expand escape sequences
  39.  */
  40.  
  41.     register char  *s;
  42.     register unsigned char  *t;
  43.     register char  *pstr;
  44.     register int    i;
  45.     register int    val;
  46.     register int    autoinc;
  47.     char        c;
  48.     char        fs[5];                /* for font change */
  49.     char        nrstr[20];
  50.     char        fmt[20];
  51.     char        name[10];
  52.     int        nreg;
  53.     char           *pfs;
  54.     int        inc;
  55.     int        tmp;
  56.     char        delim;
  57.  
  58.  
  59.     s = p;
  60.     t = q;
  61.  
  62.  
  63.     /*
  64.      *   if escape parsing is not on, just copy string
  65.      */
  66.     if (dc.escon == NO)
  67.     {
  68.         while (*s != EOS)
  69.         {
  70.             *t++ = *s++;
  71.         }
  72.         *t = EOS;
  73.         strcpy (p, q);
  74.  
  75.         return;
  76.     }
  77.  
  78.  
  79.     /*
  80.      *   do it...
  81.      */
  82.     while (*s != EOS)
  83.     {
  84.         if (*s != dc.escchr)
  85.         {
  86.             /*
  87.              *   not esc, continue...
  88.              */
  89.             *t++ = *s++;
  90.         }
  91.  
  92.  
  93.         else if (*(s + 1) == dc.escchr)
  94.         {
  95.             /*
  96.              *   \\            escape escape
  97.              */
  98.             *t++ = *s++;
  99.             ++s;
  100.         }
  101.  
  102.  
  103.         else if (*(s + 1) == 'n')
  104.         {
  105.             /*
  106.              *   \nx, \n(xx        register
  107.              *
  108.              *   first check for \n+... or \n-... (either form)
  109.              */
  110.             s += 2;
  111.             autoinc = 0;
  112.             if (*s == '+')
  113.             {
  114.                 autoinc = 1;
  115.                 s += 1;
  116.             }
  117.             if (*s == '-')
  118.             {
  119.                 autoinc = -1;
  120.                 s += 1;
  121.             }
  122.  
  123.  
  124.  
  125.             /*
  126.              *   was this \nx or \n(xx form?
  127.              */
  128.             if (isalpha (*s))
  129.             {
  130.                 /*
  131.                  *   \nx form. find reg (a-z)
  132.                  */
  133.                 nreg = tolower (*s) - 'a';
  134.  
  135.  
  136.                 /*
  137.                  *   was this \n+x or \n-x? if so, do the
  138.                  *   auto incr
  139.                  */
  140.                 if (autoinc > 0)
  141.                     dc.nr[nreg] += dc.nrauto[nreg];
  142.                 else if (autoinc < 0)
  143.                     dc.nr[nreg] -= dc.nrauto[nreg];
  144.  
  145.                 /*
  146.                  *   display format
  147.                  */
  148.                 if (dc.nrfmt[nreg] == '1')
  149.                 {
  150.                     /*
  151.                      *   normal decimal digits
  152.                      */
  153.                     t += itoda (dc.nr[nreg], t, 6) - 1;
  154.                 }
  155.                 else if (dc.nrfmt[nreg] == 'i')
  156.                 {
  157.                     /*
  158.                      *   lower roman
  159.                      */
  160.                     t += itoroman (dc.nr[nreg], t, 24) - 1;
  161.                 }
  162.                 else if (dc.nrfmt[nreg] == 'I')
  163.                 {
  164.                     /*
  165.                      *   upper roman
  166.                      */
  167.                     t += itoROMAN (dc.nr[nreg], t, 24) - 1;
  168.                 }
  169.                 else if (dc.nrfmt[nreg] == 'a')
  170.                 {
  171.                     /*
  172.                      *   lower letters
  173.                      */
  174.                     t += itoletter (dc.nr[nreg], t, 12) - 1;
  175.                 }
  176.                 else if (dc.nrfmt[nreg] == 'A')
  177.                 {
  178.                     /*
  179.                      *   upper letters
  180.                      */
  181.                     t += itoLETTER (dc.nr[nreg], t, 12) - 1;
  182.                 }
  183.                 else if (dc.nrfmt[nreg] & 0x80)
  184.                 {
  185.                     /*
  186.                      *   zero-filled decimal
  187.                      */
  188.                     sprintf (fmt, "%%0%dld",
  189.                         (int)(dc.nrfmt[nreg] & 0x7F));
  190.                     fmt[5] = '\0';
  191.                     sprintf (nrstr, fmt, (long) dc.nr[nreg]);
  192.                     tmp = dc.nrfmt[nreg] & 0x7F;
  193.                     nrstr[tmp] = '\0';
  194.  
  195.                     strcpy (t, nrstr);
  196.                     t += strlen (nrstr);
  197.                 }
  198.                 else
  199.                 {
  200.                     /*
  201.                      *   normal (default)
  202.                      */
  203.                     t += itoda (dc.nr[nreg], t, 6) - 1;
  204.                 }
  205.                 ++s;
  206.             }
  207.             else if (*s == '%')
  208.             {
  209.                 /*
  210.                  *   \n% form. find index into reg struct
  211.                  */
  212.                 nreg = findreg ("%");
  213.                 if (nreg < 0)
  214.                 {
  215.                     fprintf (err_stream,
  216.                         "***%s: no register match\n",
  217.                         myname);
  218.                     err_exit (-1);
  219.                 }
  220.  
  221.  
  222.                 /*
  223.                  *   was this \n+% or \n-%? if so, do the
  224.                  *   auto incr
  225.                  */
  226.                 if (autoinc > 0)
  227.                     rg[nreg].rval += rg[nreg].rauto;
  228.                 else if (autoinc < 0)
  229.                     rg[nreg].rval -= rg[nreg].rauto;
  230.  
  231.  
  232.                 /*
  233.                  *   display format
  234.                  */
  235.                 if (rg[nreg].rfmt == '1')
  236.                 {
  237.                     /*
  238.                      *   normal decimal digits
  239.                      */
  240.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  241.                 }
  242.                 else if (rg[nreg].rfmt == 'i')
  243.                 {
  244.                     /*
  245.                      *   lower roman
  246.                      */
  247.                     t += itoroman (rg[nreg].rval, t, 24) - 1;
  248.                 }
  249.                 else if (rg[nreg].rfmt == 'I')
  250.                 {
  251.                     /*
  252.                      *   upper roman
  253.                      */
  254.                     t += itoROMAN (rg[nreg].rval, t, 24) - 1;
  255.                 }
  256.                 else if (rg[nreg].rfmt == 'a')
  257.                 {
  258.                     /*
  259.                      *   lower letters
  260.                      */
  261.                     t += itoletter (rg[nreg].rval, t, 12) - 1;
  262.                 }
  263.                 else if (rg[nreg].rfmt == 'A')
  264.                 {
  265.                     /*
  266.                      *   upper letters
  267.                      */
  268.                     t += itoLETTER (rg[nreg].rval, t, 12) - 1;
  269.                 }
  270.                 else if (rg[nreg].rfmt & 0x80)
  271.                 {
  272.                     /*
  273.                      *   zero-filled decimal
  274.                      */
  275.                     sprintf (fmt, "%%0%dld",
  276.                         (int)(rg[nreg].rfmt & 0x7F));
  277.                     fmt[5] = '\0';
  278.                     sprintf (nrstr, fmt, (long) rg[nreg].rval);
  279.                     tmp = rg[nreg].rfmt & 0x7F;
  280.                     nrstr[tmp] = '\0';
  281.  
  282.                     strcpy (t, nrstr);
  283.                     t += strlen (nrstr);
  284.                 }
  285.                 else
  286.                 {
  287.                     /*
  288.                      *   normal (default)
  289.                      */
  290.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  291.                 }
  292.                 s += 1;
  293.             }
  294.             else if (*s == '(')
  295.             {
  296.                 /*
  297.                  *   \n(xx form. find index into reg struct
  298.                  */
  299.                 s += 1;
  300.                 name[0] = *s;
  301.                 name[1] = *(s + 1);
  302.                 if (name[1] == ' '  || name[1] == '\t'
  303.                 ||  name[1] == '\n' || name[1] == '\r')
  304.                     name[1] = '\0';
  305.                 name[2] = '\0';
  306.                 nreg = findreg (name);
  307.                 if (nreg < 0)
  308.                 {
  309.                     fprintf (err_stream,
  310.                         "***%s: no register match\n",
  311.                         myname);
  312.                     err_exit (-1);
  313.                 }
  314.                 
  315.  
  316.                 /*
  317.                  *   was this \n+(xx or \n-(xx? if so, do the
  318.                  *   auto incr
  319.                  */
  320.                 if (rg[nreg].rflag & RF_WRITE)
  321.                 {
  322.                     if (autoinc > 0)
  323.                         rg[nreg].rval += rg[nreg].rauto;
  324.                     else if (autoinc < 0)
  325.                         rg[nreg].rval -= rg[nreg].rauto;
  326.                 }
  327.  
  328.  
  329.                 /*
  330.                  *   display format
  331.                  */
  332.                 if (rg[nreg].rfmt == '1')
  333.                 {
  334.                     /*
  335.                      *   normal decimal digits
  336.                      */
  337.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  338.                 }
  339.                 else if (rg[nreg].rfmt == 'i')
  340.                 {
  341.                     /*
  342.                      *   lower roman
  343.                      */
  344.                     t += itoroman (rg[nreg].rval, t, 24) - 1;
  345.                 }
  346.                 else if (rg[nreg].rfmt == 'I')
  347.                 {
  348.                     /*
  349.                      *   upper roman
  350.                      */
  351.                     t += itoROMAN (rg[nreg].rval, t, 24) - 1;
  352.                 }
  353.                 else if (rg[nreg].rfmt == 'a')
  354.                 {
  355.                     /*
  356.                      *   lower letters
  357.                      */
  358.                     t += itoletter (rg[nreg].rval, t, 12) - 1;
  359.                 }
  360.                 else if (rg[nreg].rfmt == 'A')
  361.                 {
  362.                     /*
  363.                      *   upper letters
  364.                      */
  365.                     t += itoLETTER (rg[nreg].rval, t, 12) - 1;
  366.                 }
  367.                 else if (rg[nreg].rfmt & 0x80)
  368.                 {
  369.                     /*
  370.                      *   zero-filled decimal
  371.                      */
  372.                     sprintf (fmt, "%%0%dld",
  373.                         (int)(rg[nreg].rfmt & 0x7F));
  374.                     fmt[5] = '\0';
  375.                     sprintf (nrstr, fmt, (long) rg[nreg].rval);
  376.                     tmp = rg[nreg].rfmt & 0x7F;
  377.                     nrstr[tmp] = '\0';
  378.  
  379.                     strcpy (t, nrstr);
  380.                     t += strlen (nrstr);
  381.                 }
  382.                 else
  383.                 {
  384.                     /*
  385.                      *   normal (default)
  386.                      */
  387.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  388.                 }
  389.                 s += 2;
  390.             }
  391.         }
  392.  
  393.  
  394.         else if (*(s + 1) == '\"')
  395.         {
  396.             /*
  397.              *   \"            comment
  398.              */
  399.             *s = EOS;
  400.             *t = *s;
  401.  
  402.             return;
  403.         }
  404.  
  405.  
  406.         else if (*(s + 1) == '*')
  407.         {
  408.             /*
  409.              *   \*x, \*(xx        string
  410.              */
  411.             s += 2;
  412.             if (*s == '(')
  413.             {
  414.                 /*
  415.                  *   \*(xx form
  416.                  */
  417.                 s += 1;
  418.                 name[0] = *s;
  419.                 name[1] = *(s + 1);
  420.                 name[2] = '\0';
  421.                 pstr = getstr (name);
  422.                 if (!pstr)
  423.                 {
  424.                     fprintf (err_stream,
  425.                         "***%s: string not found\n",
  426.                         myname);
  427.                     err_exit (-1);
  428.                 }
  429.                 while (*pstr)
  430.                     *t++ = *pstr++;
  431.                 s += 2;
  432.             }
  433.             else
  434.             {
  435.                 /*
  436.                  *   \*x form
  437.                  */
  438.                 name[0] = *s;
  439.                 name[1] = '\0';
  440.                 pstr = getstr (name);
  441.                 if (!pstr)
  442.                 {
  443.                     fprintf (err_stream,
  444.                         "***%s: string not found\n",
  445.                         myname);
  446.                     err_exit (-1);
  447.                 }
  448.                 while (*pstr)
  449.                     *t++ = *pstr++;
  450.                 s += 1;
  451.             }
  452.         }
  453.  
  454.  
  455.         else if (*(s + 1) == 'f')
  456.         {
  457.             /*
  458.              *   \fx        font
  459.              */
  460.             s += 2;
  461.             pfs = fs;        /* set up ret string */
  462.             fs[0] = '\0';
  463.  
  464.             /*
  465.              *  it parses 1-2 char of s and returns esc seq for
  466.              *  \fB and \fR (\fI is same as \fB)
  467.              */
  468.             fontchange (*s, pfs);
  469.  
  470.             /*
  471.              *   imbed the atari (vt52) escape seq
  472.              */
  473.             while (*pfs)
  474.                 *t++ = *pfs++;
  475.             ++s;            /* skip B,I,R,S,P */
  476.         }
  477.  
  478.  
  479.         else if (*(s + 1) == '(')
  480.         {
  481.             /*
  482.              *   \(xx        special char
  483.              */
  484.             s  += 2;
  485.  
  486.             /*
  487.              *   it returns num char to skip and sets c to
  488.              *   the ascii value of the char
  489.              */
  490.             inc = specialchar (s, &c);
  491.  
  492.             /*
  493.              *   skip proper num char in s and add c to target
  494.              */
  495.             if (inc)
  496.             {
  497.                 s   += inc;
  498.                 *t++ = c;
  499.             }
  500.         }
  501.  
  502.  
  503.         else if (*(s + 1) == 'e')
  504.         {
  505.             /*
  506.              *   \e        printable version of escape
  507.              */
  508.             *t++ = dc.escchr;
  509.             s   += 2;
  510.         }
  511.  
  512.  
  513.         else if (*(s + 1) == '`')
  514.         {
  515.             /*
  516.              *   \`        grave, like \(ga
  517.              */
  518.             *t++ = 0x60;
  519.             s  += 2;
  520.         }
  521.  
  522.  
  523.         else if (*(s + 1) == '\'')
  524.         {
  525.             /*
  526.              *   \'        accute, like \(aa
  527.              */
  528.             s  += 2;
  529. #ifdef LATIN1
  530.             *t++ = 0xB4;
  531. #else
  532.             *t++ = 0xBA;
  533. #endif
  534.         }
  535.  
  536.  
  537.         else if (*(s + 1) == '-')
  538.         {
  539.             /*
  540.              *   \-        minus
  541.              */
  542.             s  += 2;
  543.             *t++ = 0x2D;
  544.         }
  545.  
  546.  
  547.         else if (*(s + 1) == '.')
  548.         {
  549.             /*
  550.              *   \.        period
  551.              */
  552.             s  += 2;
  553.             *t++ = 0x2E;
  554.         }
  555.  
  556.  
  557.         else if (*(s + 1) == ' ')
  558.         {
  559.             /*
  560.              *   \(space)    space
  561.              */
  562.             s  += 2;
  563.             *t++ = 0x20;
  564.         }
  565.  
  566.  
  567.         else if (*(s + 1) == '0')
  568.         {
  569.             /*
  570.              *   \0        digital width space
  571.              */
  572.             s  += 2;
  573.             *t++ = 0x20;
  574.         }
  575.  
  576.  
  577.         else if (*(s + 1) == '|')
  578.         {
  579.             /*
  580.              *   \|        narrow width char (0 in nroff)
  581.              */
  582.             s  += 2;
  583.         }
  584.  
  585.  
  586.         else if (*(s + 1) == '^')
  587.         {
  588.             /*
  589.              *   \^        narrow width char (0 in nroff)
  590.              */
  591.             s  += 2;
  592.         }
  593.  
  594.  
  595.         else if (*(s + 1) == '&')
  596.         {
  597.             /*
  598.              *   \&        non-printing zero width
  599.              */
  600.             s  += 2;
  601.         }
  602.  
  603.  
  604.         else if (*(s + 1) == '!')
  605.         {
  606.             /*
  607.              *   \!        transparent copy line
  608.              */
  609.             s  += 2;
  610.         }
  611.  
  612.  
  613.         else if (*(s + 1) == '$')
  614.         {
  615.             /*
  616.              *   \$N    interpolate arg 1<=N<=9
  617.              */
  618.             s  += 2;
  619.         }
  620.  
  621.  
  622.         else if (*(s + 1) == '%')
  623.         {
  624.             /*
  625.              *   \%        hyphen
  626.              */
  627.             s  += 2;
  628.             *t++ = 0x2D;
  629.             *t++ = 0x2D;
  630.         }
  631.  
  632.  
  633.         else if (*(s + 1) == 'a')
  634.         {
  635.             /*
  636.              *   \a
  637.              */
  638.             s  += 2;
  639.         }
  640.  
  641.  
  642.         else if (*(s + 1) == 'b')
  643.         {
  644.             /*
  645.              *   \b'abc...'
  646.              */
  647.             s  += 2;
  648.         }
  649.  
  650.  
  651.         else if (*(s + 1) == 'c')
  652.         {
  653.             /*
  654.              *   \c
  655.              */
  656.             s  += 2;
  657.         }
  658.  
  659.  
  660.         else if (*(s + 1) == 'd')
  661.         {
  662.             /*
  663.              *   \d
  664.              */
  665.             s  += 2;
  666.         }
  667.  
  668.  
  669.         else if (*(s + 1) == 'h')
  670.         {
  671.             /*
  672.              *   \h'N'    horiz motion
  673.              */
  674.             s    += 2;
  675.             delim = *s++;
  676.             val   = atoi (s);
  677.             for (i = 0; i < val; i++)
  678.                 *t++ = ' ';
  679.             while (*s != delim)
  680.             {
  681.                 if (*s == 0)
  682.                     break;
  683.                 s++;
  684.             }
  685.             if (*s)
  686.                 s++;
  687.             
  688.         }
  689.  
  690.  
  691.         else if (*(s + 1) == 'k')
  692.         {
  693.             /*
  694.              *   \kx
  695.              */
  696.             s  += 2;
  697.         }
  698.  
  699.  
  700.         else if (*(s + 1) == 'l')
  701.         {
  702.             /*
  703.              *   \l'Nc'
  704.              */
  705.             s  += 2;
  706.         }
  707.  
  708.  
  709.         else if (*(s + 1) == 'L')
  710.         {
  711.             /*
  712.              *   \L'Nc'
  713.              */
  714.             s  += 2;
  715.         }
  716.  
  717.  
  718.         else if (*(s + 1) == 'o')
  719.         {
  720.             /*
  721.              *   \o'abc...'        overstrike
  722.              */
  723.             s  += 2;
  724.             delim = *s++;
  725.             while (*s != EOS && *s != delim)
  726.             {
  727.                 *t++ = *s++;
  728.                 *t++ = 0x08;
  729.             }
  730.             s++;
  731.         }
  732.  
  733.  
  734.         else if (*(s + 1) == 'p')
  735.         {
  736.             /*
  737.              *   \p
  738.              */
  739.             s  += 2;
  740.         }
  741.  
  742.  
  743.         else if (*(s + 1) == 'r')
  744.         {
  745.             /*
  746.              *   \r
  747.              */
  748.             s  += 2;
  749.         }
  750.  
  751.  
  752.         else if (*(s + 1) == 's')
  753.         {
  754.             /*
  755.              *   \sN,\s+-N
  756.              */
  757.             s  += 2;
  758.         }
  759.  
  760.  
  761.         else if (*(s + 1) == 't')
  762.         {
  763.             /*
  764.              *   \t        horizontal tab
  765.              */
  766.             s  += 2;
  767.             *t++ = 0x09;
  768.         }
  769.  
  770.  
  771.         else if (*(s + 1) == 'u')
  772.         {
  773.             /*
  774.              *   \u
  775.              */
  776.             s  += 2;
  777.         }
  778.  
  779.  
  780.         else if (*(s + 1) == 'v')
  781.         {
  782.             /*
  783.              *   \v'N'    vert tab
  784.              */
  785.             s    += 2;
  786.             delim = *s++;
  787.             val   = atoi (s);
  788.             for (i = 0; i < val; i++)
  789.                 *t++ = 0x0A;
  790.             while (*s != delim)
  791.             {
  792.                 if (*s == 0)
  793.                     break;
  794.                 s++;
  795.             }
  796.             if (*s)
  797.                 s++;
  798.         }
  799.  
  800.  
  801.         else if (*(s + 1) == 'w')
  802.         {
  803.             /*
  804.              *   \w'str'
  805.              */
  806.             s  += 2;
  807.         }
  808.  
  809.  
  810.         else if (*(s + 1) == 'x')
  811.         {
  812.             /*
  813.              *   \x'N'
  814.              */
  815.             s  += 2;
  816.         }
  817.  
  818.  
  819.         else if (*(s + 1) == 'z')
  820.         {
  821.             /*
  822.              *   \zc    print c w/o spacing
  823.              */
  824.             s  += 2;
  825.             *t++ = *s++;
  826.             *t++ = 0x08;
  827.         }
  828.  
  829.  
  830.         else if (*(s + 1) == '{')
  831.         {
  832.             /*
  833.              *   \{
  834.              */
  835.             s  += 2;
  836.         }
  837.  
  838.  
  839.         else if (*(s + 1) == '}')
  840.         {
  841.             /*
  842.              *   \}
  843.              */
  844.             s  += 2;
  845.         }
  846.  
  847.  
  848.         else if (*(s + 1) == '\n' || *(s + 1) == '\r')
  849.         {
  850.             /*
  851.              *   \(newline)    ignore newline
  852.              */
  853.             s  += 2;
  854.         }
  855.  
  856.  
  857.         else
  858.         {
  859.             /*
  860.              *   \X        any other character not above
  861.              */
  862.             s   += 1;
  863.             *t++ = *s++;
  864.         }
  865.  
  866.     }
  867.  
  868.     /*
  869.      *   end the string and return it in original buf
  870.      */
  871.     *t = EOS;
  872.     strcpy (p, q);
  873. }
  874.  
  875.  
  876.  
  877.  
  878. /*------------------------------*/
  879. /*    specialchar        */
  880. /*------------------------------*/
  881. specialchar (s, c)
  882. register char  *s;
  883. register unsigned char  *c;
  884. {
  885.  
  886. /*
  887.  *    handles \(xx escape sequences for special characters (atari-specific)
  888.  */
  889.  
  890.     register char    c1;
  891.     register char    c2;
  892.  
  893.     c1 = *s;
  894.     c2 = *(s+1);
  895.  
  896.     /*
  897.      *   symbols (std font)
  898.      */
  899. #ifdef LATIN1
  900.     if (c1 == 'e' && c2 == 'm') {*c = 0xAD; return (2);}    /* dash */
  901.     if (c1 == 'h' && c2 == 'y') {*c = 0x2D; return (2);}    /* hyphen */
  902.     if (c1 == 'b' && c2 == 'u') {*c = 0xB7; return (2);}    /* bullet */
  903.     if (c1 == 's' && c2 == 'q') {*c = 0xB2; return (2);}    /* square */
  904.     if (c1 == 'r' && c2 == 'u') {*c = 0x5F; return (2);}    /* rule */
  905.     if (c1 == '1' && c2 == '4') {*c = 0xBC; return (2);}    /* 1/4 */
  906.     if (c1 == '1' && c2 == '2') {*c = 0xBD; return (2);}    /* 1/2 */
  907.     if (c1 == '3' && c2 == '4') {*c = 0xBE; return (2);}    /* 3/4 */
  908.     if (c1 == 'd' && c2 == 'e') {*c = 0xB0; return (2);}    /* degree */
  909.     if (c1 == 'f' && c2 == 'm') {*c = 0xB4; return (2);}    /* foot mark */
  910.     if (c1 == 'c' && c2 == 't') {*c = 0xA2; return (2);}    /* cent */
  911.     if (c1 == 'c' && c2 == 'o') {*c = 0xA9; return (2);}    /* copyright */
  912.     if (c1 == 'r' && c2 == 'g') {*c = 0xAE; return (2);}    /* registered */
  913.  
  914.     if (c1 == 'p' && c2 == '1') {*c = 0xB9; return (2);}    /* ^1 */
  915.     if (c1 == 'p' && c2 == '2') {*c = 0xB2; return (2);}    /* ^2 */
  916.     if (c1 == 'p' && c2 == '3') {*c = 0xB3; return (2);}    /* ^3 */
  917.     if (c1 == 'a' && c2 == 'a') {*c = 0xBA; return (2);}    /* acute */
  918.     if (c1 == 'g' && c2 == 'a') {*c = 0x60; return (2);}    /* grave */
  919.     if (c1 == 'd' && c2 == 't') {*c = 0xFA; return (2);}    /* dot */
  920.     if (c1 == 'p' && c2 == 'p') {*c = 0xB6; return (2);}    /* paragraph */
  921.     if (c1 == '^' && c2 == 'g') {*c = 0x07; return (2);}    /* ring bell */
  922.     if (c1 == 'm' && c2 == 'u') {*c = 0xD7; return (2);}    /* multiply */
  923.     if (c1 == 'd' && c2 == 'i') {*c = 0xF7; return (2);}    /* divide */
  924.     if (c1 == '+' && c2 == '-') {*c = 0xB1; return (2);}    /* +- */
  925.     if (c1 == 'a' && c2 == 'p') {*c = 0x7E; return (2);}    /* approx */
  926.     if (c1 == 'n' && c2 == 'o') {*c = 0xAC; return (2);}    /* not */
  927.     if (c1 == 'c' && c2 == 'u') {*c = 0x55; return (2);}    /* union */
  928.  
  929.     if (c1 == 'b' && c2 == 'r') {*c = 0x7C; return (2);}    /* box v rule */
  930.     if (c1 == 'b' && c2 == 'v') {*c = 0x7C; return (2);}    /* bold vert */
  931.     if (c1 == 'p' && c2 == 'l') {*c = 0x2B; return (2);}    /* math plus */
  932.     if (c1 == 'm' && c2 == 'i') {*c = 0x2D; return (2);}    /* math minus */
  933.     if (c1 == 'e' && c2 == 'q') {*c = 0x3D; return (2);}    /* math equal */
  934.     if (c1 == '*' && c2 == '*') {*c = 0x2A; return (2);}    /* math star */
  935.     if (c1 == 's' && c2 == 'l') {*c = 0x2F; return (2);}    /* slash */
  936.     if (c1 == 'u' && c2 == 'l') {*c = 0x5F; return (2);}    /* underrule */
  937.     if (c1 == 's' && c2 == 'c') {*c = 0xA7; return (2);}    /* section */
  938. #else
  939.     if (c1 == 'e' && c2 == 'm') {*c = 0x2D; return (2);}    /* dash */
  940.     if (c1 == 'h' && c2 == 'y') {*c = 0x2D; return (2);}    /* hyphen */
  941.     if (c1 == 'b' && c2 == 'u') {*c = 0xF9; return (2);}    /* bullet */
  942.     if (c1 == 's' && c2 == 'q') {*c = 0xFD; return (2);}    /* square */
  943.     if (c1 == 'r' && c2 == 'u') {*c = 0x5F; return (2);}    /* rule */
  944.     if (c1 == '1' && c2 == '2') {*c = 0xAB; return (2);}    /* 1/2 */
  945.     if (c1 == '1' && c2 == '4') {*c = 0xAC; return (2);}    /* 1/4 */
  946.     if (c1 == 'd' && c2 == 'e') {*c = 0xF8; return (2);}    /* degree */
  947.     if (c1 == 'd' && c2 == 'g') {*c = 0xBB; return (2);}    /* dagger */
  948.     if (c1 == 'f' && c2 == 'm') {*c = 0xBA; return (2);}    /* dagger */
  949.     if (c1 == 'c' && c2 == 't') {*c = 0x9B; return (2);}    /* cent */
  950.     if (c1 == 'c' && c2 == 'o') {*c = 0xBD; return (2);}    /* copyright */
  951.     if (c1 == 'r' && c2 == 'g') {*c = 0xBE; return (2);}    /* registered */
  952.     if (c1 == 't' && c2 == 'm') {*c = 0xBF; return (2);}    /* trademark */
  953.  
  954.     if (c1 == 'p' && c2 == '2') {*c = 0xFD; return (2);}    /* ^2 */
  955.     if (c1 == 'p' && c2 == '3') {*c = 0xFE; return (2);}    /* ^3 */
  956.     if (c1 == 'p' && c2 == 'n') {*c = 0xFC; return (2);}    /* ^n */
  957.     if (c1 == 'a' && c2 == 'a') {*c = 0xBA; return (2);}    /* acute */
  958.     if (c1 == 'g' && c2 == 'a') {*c = 0x60; return (2);}    /* grave */
  959.     if (c1 == 'd' && c2 == 't') {*c = 0xFA; return (2);}    /* dot */
  960.     if (c1 == 'p' && c2 == 'p') {*c = 0xBC; return (2);}    /* paragraph */
  961.     if (c1 == '^' && c2 == 'g') {*c = 0x07; return (2);}    /* ring bell */
  962.     if (c1 == 'u' && c2 == 'a') {*c = 0x01; return (2);}    /* up arrow */
  963.     if (c1 == 'd' && c2 == 'a') {*c = 0x02; return (2);}    /* dn arrow */
  964.     if (c1 == '-' && c2 == '>') {*c = 0x03; return (2);}    /* rt arrow */
  965.     if (c1 == '<' && c2 == '-') {*c = 0x04; return (2);}    /* lf arrow */
  966.     if (c1 == 'd' && c2 == 'i') {*c = 0xF6; return (2);}    /* divide */
  967.     if (c1 == 's' && c2 == 'r') {*c = 0xFB; return (2);}    /* sq root */
  968.     if (c1 == '=' && c2 == '=') {*c = 0xF0; return (2);}    /* == */
  969.     if (c1 == '>' && c2 == '=') {*c = 0xF2; return (2);}    /* >= */
  970.     if (c1 == '<' && c2 == '=') {*c = 0xF3; return (2);}    /* <= */
  971.     if (c1 == '+' && c2 == '-') {*c = 0xF1; return (2);}    /* +- */
  972.     if (c1 == '~' && c2 == '=') {*c = 0xF7; return (2);}    /* ~= */
  973.     if (c1 == 'a' && c2 == 'p') {*c = 0x7E; return (2);}    /* approx */
  974.     if (c1 == 'n' && c2 == 'o') {*c = 0xAA; return (2);}    /* not */
  975.     if (c1 == 'm' && c2 == 'o') {*c = 0xEE; return (2);}    /* member */
  976.     if (c1 == 'c' && c2 == 'a') {*c = 0xEF; return (2);}    /* intersect */
  977.     if (c1 == 'c' && c2 == 'u') {*c = 0x55; return (2);}    /* union */
  978.     if (c1 == 'i' && c2 == '1') {*c = 0xF4; return (2);}    /* integral1 */
  979.     if (c1 == 'i' && c2 == '2') {*c = 0xF5; return (2);}    /* integral2 */
  980.  
  981.     if (c1 == 'b' && c2 == 'r') {*c = 0x7C; return (2);}    /* box v rule */
  982.     if (c1 == 'b' && c2 == 'v') {*c = 0x7C; return (2);}    /* bold vert */
  983.     if (c1 == 'p' && c2 == 'l') {*c = 0x2B; return (2);}    /* math plus */
  984.     if (c1 == 'm' && c2 == 'i') {*c = 0x2D; return (2);}    /* math minus */
  985.     if (c1 == 'e' && c2 == 'q') {*c = 0x3D; return (2);}    /* math equal */
  986.     if (c1 == '*' && c2 == '*') {*c = 0x2A; return (2);}    /* math star */
  987.     if (c1 == 's' && c2 == 'l') {*c = 0x2F; return (2);}    /* slash */
  988.     if (c1 == 'u' && c2 == 'l') {*c = 0x5F; return (2);}    /* underrule */
  989.     if (c1 == 's' && c2 == 'c') {*c = 0xDD; return (2);}    /* section */
  990. #endif
  991.  
  992.  
  993.     /*
  994.      *   greek
  995.      */
  996. #ifdef LATIN1
  997.     if (c1 == '*' && c2 == 'm') {*c = 0xB5; return (2);}    /* mu */
  998. #else
  999.     if (c1 == '*' && c2 == 'a') {*c = 0xE0; return (2);}    /* alpha */
  1000.     if (c1 == '*' && c2 == 'b') {*c = 0xE1; return (2);}    /* beta */
  1001.     if (c1 == '*' && c2 == 'G') {*c = 0xE2; return (2);}    /* Gamma */
  1002.     if (c1 == '*' && c2 == 'd') {*c = 0xEB; return (2);}    /* delta */
  1003.     if (c1 == '*' && c2 == 'D') {*c = 0x7F; return (2);}    /* Delta */
  1004.     if (c1 == '*' && c2 == 'H') {*c = 0xE9; return (2);}    /* Theta */
  1005.     if (c1 == '*' && c2 == 'm') {*c = 0xE6; return (2);}    /* mu */
  1006.     if (c1 == '*' && c2 == 'p') {*c = 0xE3; return (2);}    /* pi */
  1007.     if (c1 == '*' && c2 == 's') {*c = 0xE5; return (2);}    /* sigma */
  1008.     if (c1 == '*' && c2 == 'S') {*c = 0xE4; return (2);}    /* Sigma */
  1009.     if (c1 == '*' && c2 == 't') {*c = 0xE7; return (2);}    /* tau */
  1010.     if (c1 == '*' && c2 == 'F') {*c = 0xE8; return (2);}    /* Phi */
  1011.     if (c1 == '*' && c2 == 'W') {*c = 0xEA; return (2);}    /* Omega */
  1012. #endif
  1013.  
  1014.     *c = ' ';
  1015.     return (0);    
  1016. }
  1017.  
  1018.  
  1019.  
  1020.  
  1021. /*------------------------------*/
  1022. /*    fontchange        */
  1023. /*------------------------------*/
  1024. fontchange (fnt, s)
  1025. char    fnt;
  1026. char   *s;
  1027. {
  1028.  
  1029. /*
  1030.  *    handles \fx font change escapes for R,B,I,S,P (atari-specific)
  1031.  *    resets current and last font in dc struct (last used for .ft
  1032.  *    with no args)
  1033.  */
  1034.  
  1035.     int    tmp;
  1036.  
  1037.     *s = '\0';
  1038.     switch (fnt)
  1039.     {
  1040.     case 'R':                /* Times Roman */
  1041.         if (dc.dofnt == YES)
  1042.             strcpy (s, e_standout);
  1043.         dc.lastfnt = dc.thisfnt;
  1044.         dc.thisfnt = 1;
  1045.         break;
  1046.     case 'I':                /* Times italic */
  1047.         if (dc.dofnt == YES)
  1048.             strcpy (s, s_standout);
  1049.         dc.lastfnt = dc.thisfnt;
  1050.         dc.thisfnt = 2;
  1051.         break;
  1052.     case 'B':                /* Times bold */
  1053.         if (dc.dofnt == YES)
  1054.             strcpy (s, s_standout);
  1055.         dc.lastfnt = dc.thisfnt;
  1056.         dc.thisfnt = 3;
  1057.         break;
  1058.     case 'S':                /* math/special */
  1059.         *s = '\0';
  1060.         dc.lastfnt = dc.thisfnt;
  1061.         dc.thisfnt = 4;
  1062.         break;
  1063.     case 'P':                /* previous (exchange) */
  1064.         if (dc.dofnt == YES)
  1065.         {
  1066.             if (dc.lastfnt == 1)
  1067.                 strcpy (s, e_standout);    /* to R */
  1068.             else if (dc.lastfnt == 2)
  1069.                 strcpy (s, s_standout);    /* to I */
  1070.             else if (dc.lastfnt == 3)
  1071.                 strcpy (s, s_standout);    /* to B */
  1072.             else
  1073.                 *s = '\0';        /* nothing */
  1074.         }
  1075.  
  1076.         tmp        = dc.thisfnt;        /* swap this/last */
  1077.         dc.thisfnt = dc.lastfnt;
  1078.         dc.lastfnt = tmp;
  1079.         break;
  1080.     default:
  1081.         *s = '\0';
  1082.         break;
  1083.     }
  1084.  
  1085.     set_ireg (".f", dc.thisfnt, 0);
  1086. }
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092. /*------------------------------*/
  1093. /*    findreg            */
  1094. /*------------------------------*/
  1095. findreg (name)
  1096. register char  *name;
  1097. {
  1098.  
  1099. /*
  1100.  *    find register named 'name' in pool. return index into array or -1
  1101.  *    if not found.
  1102.  */
  1103.  
  1104.     register int    i;
  1105.     register char  *prname;
  1106.  
  1107.     for (i = 0; i < MAXREGS; i++)
  1108.     {
  1109.         prname = rg[i].rname;
  1110.         if (*prname == *name && *(prname + 1) == *(name + 1))
  1111.             break;
  1112.     }
  1113.  
  1114.     return ((i < MAXREGS) ? i : -1);
  1115. }
  1116.  
  1117.  
  1118.  
  1119.  
  1120.